#include <mysql/mysql.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <linux/time.h>

// 连接池配置
#define MAX_POOL_SIZE 20
#define MIN_POOL_SIZE 3
#define CONNECTION_TIMEOUT 10      // 秒
#define MAX_IDLE_TIME 180           // 秒 (3分钟)
#define HEALTH_CHECK_INTERVAL 30    // 秒 (健康检查间隔)

// 连接状态
typedef enum {
    POOL_CONN_FREE,     // 空闲可用
    POOL_CONN_IN_USE,   // 正在使用
    POOL_CONN_BROKEN    // 连接已损坏
} PoolConnStatus;

// 连接节点
typedef struct PoolConnection {
    MYSQL *conn;             // MySQL连接
    PoolConnStatus status;   // 连接状态
    time_t last_used;        // 最后使用时间
    time_t created_at;       // 创建时间
    struct PoolConnection *next;
} PoolConnection;

// 连接池
typedef struct {
    PoolConnection *connections;  // 连接链表的头指针
    int size;                     // 当前连接数
    int active_count;             // 活跃连接数
    pthread_mutex_t lock;         // 互斥锁
    pthread_cond_t cond;           // 条件变量
    
    // 数据库连接参数
    char host[64];
    char username[64];
    char password[64];
    char database[64];
    unsigned int port;
    bool initialized;             // 是否已初始化
} ConnectionPool;

// 创建新连接
static MYSQL *create_db_connection(ConnectionPool *pool) {
    MYSQL *conn = mysql_init(NULL);
    if (!conn) return NULL;

    // 设置连接选项
    unsigned int connect_timeout = 5;
    unsigned int read_timeout = 10;
    mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout);
    mysql_options(conn, MYSQL_OPT_READ_TIMEOUT, &read_timeout);
    mysql_options(conn, MYSQL_SET_CHARSET_NAME, "utf8mb4");

    // 实际连接数据库
    if (!mysql_real_connect(conn, pool->host, pool->username, pool->password, 
                           pool->database, pool->port, NULL, 0)) {
        fprintf(stderr, "连接失败: %s\n", mysql_error(conn));
        mysql_close(conn);
        return NULL;
    }
    
    return conn;
}

// 初始化连接池
ConnectionPool *connection_pool_create(const char *host, const char *username, 
                                      const char *password, const char *database, 
                                      unsigned int port) {
    ConnectionPool *pool = malloc(sizeof(ConnectionPool));
    if (!pool) return NULL;
    
    // 初始化参数
    strncpy(pool->host, host, sizeof(pool->host)-1);
    strncpy(pool->username, username, sizeof(pool->username)-1);
    strncpy(pool->password, password, sizeof(pool->password)-1);
    strncpy(pool->database, database, sizeof(pool->database)-1);
    pool->port = port;
    pool->size = 0;
    pool->active_count = 0;
    pool->connections = NULL;
    pool->initialized = false;
    
    // 初始化互斥锁和条件变量
    if (pthread_mutex_init(&pool->lock, NULL) != 0) {
        free(pool);
        return NULL;
    }
    
    if (pthread_cond_init(&pool->cond, NULL) != 0) {
        pthread_mutex_destroy(&pool->lock);
        free(pool);
        return NULL;
    }
    
    // 创建初始连接
    for (int i = 0; i < MIN_POOL_SIZE; i++) {
        MYSQL *conn = create_db_connection(pool);
        if (!conn) continue;
        
        PoolConnection *node = malloc(sizeof(PoolConnection));
        if (!node) {
            mysql_close(conn);
            continue;
        }
        
        node->conn = conn;
        node->status = POOL_CONN_FREE;
        node->last_used = time(NULL);
        node->created_at = time(NULL);
        
        // 添加到链表头部
        node->next = pool->connections;
        pool->connections = node;
        pool->size++;
    }
    
    if (pool->size > 0) {
        pool->initialized = true;
    }
    
    return pool;
}

// 获取数据库连接
MYSQL *connection_pool_acquire(ConnectionPool *pool) {
    if (!pool || !pool->initialized) return NULL;
    
    pthread_mutex_lock(&pool->lock);
    
    PoolConnection *node = NULL;
    time_t start_time = time(NULL);
    
    // 尝试获取空闲连接
    while (true) {
        // 遍历查找空闲连接
        for (PoolConnection *curr = pool->connections; curr != NULL; curr = curr->next) {
            if (curr->status == POOL_CONN_FREE) {
                node = curr;
                break;
            }
        }
        
        // 找到空闲连接
        if (node) {
            node->status = POOL_CONN_IN_USE;
            node->last_used = time(NULL);
            pool->active_count++;
            break;
        }
        
        // 可以创建新连接
        if (pool->size < MAX_POOL_SIZE) {
            MYSQL *new_conn = create_db_connection(pool);
            if (new_conn) {
                node = malloc(sizeof(PoolConnection));
                if (node) {
                    node->conn = new_conn;
                    node->status = POOL_CONN_IN_USE;
                    node->last_used = time(NULL);
                    node->created_at = time(NULL);
                    
                    // 添加到链表头部
                    node->next = pool->connections;
                    pool->connections = node;
                    
                    pool->size++;
                    pool->active_count++;
                    break;
                } else {
                    mysql_close(new_conn);
                }
            }
        }
        
        // 等待可用连接
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        ts.tv_sec += CONNECTION_TIMEOUT;
        
        int rc = pthread_cond_timedwait(&pool->cond, &pool->lock, &ts);
        if (rc == ETIMEDOUT) {
            pthread_mutex_unlock(&pool->lock);
            return NULL;
        }
    }
    
    pthread_mutex_unlock(&pool->lock);
    return node->conn;
}

// 释放数据库连接
void connection_pool_release(ConnectionPool *pool, MYSQL *conn) {
    if (!pool || !conn || !pool->initialized) return;
    
    pthread_mutex_lock(&pool->lock);
    
    // 查找对应的连接节点
    PoolConnection *node = NULL;
    for (PoolConnection *curr = pool->connections; curr != NULL; curr = curr->next) {
        if (curr->conn == conn) {
            node = curr;
            break;
        }
    }
    
    if (!node) {
        pthread_mutex_unlock(&pool->lock);
        return;
    }
    
    // 检查连接健康
    if (mysql_ping(conn) != 0) {
        node->status = POOL_CONN_BROKEN;
    } else {
        node->status = POOL_CONN_FREE;
        node->last_used = time(NULL);
    }
    
    pool->active_count--;
    
    // 通知等待线程
    pthread_cond_signal(&pool->cond);
    pthread_mutex_unlock(&pool->lock);
}

// 维护连接池：可扩展
void connection_pool_maintain(ConnectionPool *pool) {
    if (!pool || !pool->initialized) return;
    
    pthread_mutex_lock(&pool->lock);
    
    time_t now = time(NULL);
    PoolConnection **curr = &pool->connections;
    
    while (*curr) {
        PoolConnection *node = *curr;
        
        // 处理损坏的连接
        if (node->status == POOL_CONN_BROKEN) {
            *curr = node->next;
            mysql_close(node->conn);
            free(node);
            pool->size--;
            continue;
        }
        
        // 处理空闲超时的连接
        if (node->status == POOL_CONN_FREE && 
            (now - node->last_used) > MAX_IDLE_TIME && 
            pool->size > MIN_POOL_SIZE) {
            *curr = node->next;
            mysql_close(node->conn);
            free(node);
            pool->size--;
            continue;
        }
        
        // 定期检查连接健康
        if (node->status == POOL_CONN_FREE && 
            (now - node->last_used) > HEALTH_CHECK_INTERVAL) {
            if (mysql_ping(node->conn) != 0) {
                node->status = POOL_CONN_BROKEN;
            }
        }
        
        curr = &node->next;
    }
    
    pthread_mutex_unlock(&pool->lock);
}

// 销毁连接池
void connection_pool_destroy(ConnectionPool *pool) {
    if (!pool) return;
    
    pthread_mutex_lock(&pool->lock);
    
    PoolConnection *curr = pool->connections;
    while (curr) {
        PoolConnection *next = curr->next;
        mysql_close(curr->conn);
        free(curr);
        curr = next;
    }
    
    pthread_mutex_unlock(&pool->lock);
    pthread_mutex_destroy(&pool->lock);
    pthread_cond_destroy(&pool->cond);
    
    free(pool);
}

// 打印连接池状态
void connection_pool_stats(ConnectionPool *pool) {
    if (!pool || !pool->initialized) return;
    
    pthread_mutex_lock(&pool->lock);
    
    int free_count = 0, in_use_count = 0, broken_count = 0;
    for (PoolConnection *curr = pool->connections; curr != NULL; curr = curr->next) {
        switch (curr->status) {
            case POOL_CONN_FREE: free_count++; break;
            case POOL_CONN_IN_USE: in_use_count++; break;
            case POOL_CONN_BROKEN: broken_count++; break;
        }
    }
    
    printf("===== 连接池状态 =====\n");
    printf("总连接数: %d\n", pool->size);
    printf("活跃连接: %d\n", pool->active_count);
    printf("空闲连接: %d\n", free_count);
    printf("使用中连接: %d\n", in_use_count);
    printf("损坏连接: %d\n", broken_count);
    printf("数据库: %s@%s:%u\n", pool->database, pool->host, pool->port);
    printf("======================\n");
    
    pthread_mutex_unlock(&pool->lock);
}

#define NUM_THREADS 15       // 测试线程数量
#define OPERATIONS_PER_THREAD 10 // 每个线程执行的操作次数

// 线程参数结构
typedef struct {
    ConnectionPool *pool;    // 连接池指针
    int thread_id;           // 线程ID
    int success_count;       // 成功操作计数
    int failure_count;       // 失败操作计数
} ThreadData;

// 线程工作函数
void *thread_work(void *arg) {
    ThreadData *data = (ThreadData *)arg;
    ConnectionPool *pool = data->pool;
    
    printf("线程 %d 启动\n", data->thread_id);
    
    for (int i = 0; i < OPERATIONS_PER_THREAD; i++) {
        // 随机等待0-100毫秒，模拟实际工作负载
        usleep(rand() % 100000);
        
        // 获取连接
        MYSQL *conn = connection_pool_acquire(pool);
        if (!conn) {
            printf("线程 %d 操作 %d: 获取连接失败\n", data->thread_id, i+1);
            data->failure_count++;
            continue;
        }
        
        // 执行简单查询
        const char *query = "SELECT 1";
        if (mysql_query(conn, query) != 0) {
            printf("线程 %d 操作 %d: 查询失败: %s\n", 
                   data->thread_id, i+1, mysql_error(conn));
            data->failure_count++;
        } else {
            MYSQL_RES *result = mysql_store_result(conn);
            if (result) {
                mysql_free_result(result);
                data->success_count++;
                printf("线程 %d 操作 %d: 查询成功\n", data->thread_id, i+1);
            } else {
                printf("线程 %d 操作 %d: 结果集为空\n", data->thread_id, i+1);
                data->failure_count++;
            }
        }
        
        // 随机等待0-50毫秒，模拟处理时间
        usleep(rand() % 50000);
        
        // 释放连接
        connection_pool_release(pool, conn);
    }
    
    printf("线程 %d 完成: 成功 %d, 失败 %d\n", 
           data->thread_id, data->success_count, data->failure_count);
    
    return NULL;
}

// 多线程测试主函数
int main() {
    // 1. 创建连接池
    ConnectionPool *pool = connection_pool_create(
        "192.168.65.128", 
        "root", 
        "Lg@12345678", 
        "test", 
        3306
    );
    
    if (!pool || !pool->initialized) {
        fprintf(stderr, "无法创建连接池\n");
        return 1;
    }
    
    printf("连接池创建成功\n");
    connection_pool_stats(pool);
    
    // 2. 创建线程
    pthread_t threads[NUM_THREADS];
    ThreadData thread_data[NUM_THREADS];
    
    // 初始化线程数据
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_data[i].pool = pool;
        thread_data[i].thread_id = i + 1;
        thread_data[i].success_count = 0;
        thread_data[i].failure_count = 0;
    }
    
    // 3. 创建并启动线程
    for (int i = 0; i < NUM_THREADS; i++) {
        if (pthread_create(&threads[i], NULL, thread_work, &thread_data[i]) != 0) {
            perror("无法创建线程");
            continue;
        }
    }
    
    // 4. 等待所有线程完成
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    // 5. 打印连接池状态
    printf("\n所有线程已完成\n");
    connection_pool_stats(pool);
    
    // 6. 打印汇总结果
    int total_success = 0;
    int total_failure = 0;
    for (int i = 0; i < NUM_THREADS; i++) {
        total_success += thread_data[i].success_count;
        total_failure += thread_data[i].failure_count;
    }
    
    printf("\n测试结果汇总:\n");
    printf("总操作次数: %d\n", total_success + total_failure);
    printf("成功操作: %d\n", total_success);
    printf("失败操作: %d\n", total_failure);
    printf("成功率: %.2f%%\n", (float)total_success / (total_success + total_failure) * 100);
    
    // 7. 维护连接池
    printf("\n执行连接池维护...\n");
    connection_pool_maintain(pool);
    connection_pool_stats(pool);
    
    // 8. 销毁连接池
    connection_pool_destroy(pool);
    printf("连接池已销毁\n");
    
    return 0;
}